package com.qen.common;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import com.qen.repository.LambdaDao;
import org.beetl.sql.clazz.kit.BeetlSQLException;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 实体类Dao管理
 *
 * @author licz
 * @data 2025年05月15日 1:55 PM
 */
public class TableDaoHelper {

    private static final Map<Class<?>, Class<?>> CACHE = new ConcurrentHashMap<>();
    private static final Map<Class<?>, Class<?>> CACHE_REVERSE = new ConcurrentHashMap<>();
    private static final Map<String, Class<?>> CACHE_DAO = new ConcurrentHashMap<>();

    static {
        String basePackage = "com.qen";
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AssignableTypeFilter(LambdaDao.class));
        Set<Class<?>> classes = provider.findCandidateComponents(basePackage)
                .stream()
                .map(beanDefinition -> {
                    try {
                        return Class.forName(beanDefinition.getBeanClassName());
                    } catch (ClassNotFoundException e) {
                        throw new BeetlSQLException(BeetlSQLException.MAPPER_ERROR, "找不到类", e);
                    }
                }).collect(Collectors.toSet());
        for (Class<?> clazz : classes) {
            Type[] interfaces = clazz.getGenericInterfaces();
            for (Type type : interfaces) {
                if (type instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) type;
                    if (pt.getRawType() instanceof Class<?>) {
                        Class<?> rawType = (Class<?>) pt.getRawType();
                        if (rawType.equals(LambdaDao.class)) {
                            Type tType = pt.getActualTypeArguments()[0];
                            if (tType instanceof Class<?>) {
                                CACHE_REVERSE.put(clazz, (Class<?>) tType);
                                CACHE.put((Class<?>) tType, clazz);
                                CACHE_DAO.put(clazz.getName(), clazz);
                            }
                        }
                    }
                }

            }
        }

        CACHE_REVERSE.forEach((k, v) -> {
            Console.log("{}  =>  {}", k, v);
        });
        CACHE.forEach((k, v) -> {
            Console.log("{}  =>  {}", k, v);
        });
        CACHE_DAO.forEach((k, v) -> {
            Console.log("{}  =>  {}", k, v);
        });

    }

    /**
     * 初始化
     *
     * @param clazz
     * @param dao
     */
    public static void init(Class<?> clazz, Class<?> dao) {
        if (clazz != null && dao != null) {
            if (!CACHE.containsKey(clazz) || LambdaDao.class.isAssignableFrom(dao)) {
                CACHE.put(clazz, dao);
                CACHE_REVERSE.put(dao, clazz);
                CACHE_DAO.put(dao.getName(), dao);
            }
        }
    }

    /**
     * 取Dao
     *
     * @param clazz
     * @return
     */
    public static Class<?> getDao(Class<?> clazz) {
        return Optional.ofNullable(clazz).map(m -> CACHE.get(clazz)).orElse(null);
    }

    /**
     * 取Entity
     *
     * @param clazz
     * @return
     */
    public static Class<?> getEntity(Class<?> clazz) {
        return Optional.ofNullable(clazz).map(m -> CACHE_REVERSE.get(clazz)).orElse(null);
    }

    /**
     * 根据类名取Dao
     *
     * @param name
     * @return
     */
    public static Class<?> getDaoForName(String name) {
        if (StrUtil.isBlank(name)) {
            return null;
        }
        return CACHE_DAO.get(name);
    }

}
